#include "Gameplay.h"

Gameplay::Gameplay(void)
{
}

Gameplay::~Gameplay(void)
{
}

void Gameplay::Init(IDirect3DDevice9 *m_Device, HWND hWnd, HINSTANCE hInst,  int nWidth, int nHeight)
{
	// Set the device
	m_pD3DDevice = m_Device;
	// Create the DirectInput object
	m_pDirectInput = new DirectInput(hWnd, hInst);
	//////////////////////////////////////////////////////////
	// INITIALIZE & GET INSTANCES OF CLASSES
	m_pCamera = Camera::GetInstance();
	m_pCamera->InitCamera(m_pD3DDevice, nHeight, nWidth);
	m_pModelManager = ModelManager::GetInstance();
	m_pModelManager->InitModelManager(m_pD3DDevice);
	m_pSpriteManager = SpriteManager::GetInstance();
	m_pSpriteManager->InitSpriteManager(m_pD3DDevice);
	m_pObstacleManager = ObstacleManager::GetInstance();
	m_pObstacleManager->InitObstacleManager(m_pD3DDevice);
	m_pMainMenu = MainMenu::GetInstance();
	m_pMainMenu->InitMainMenu(m_pD3DDevice, hWnd, hInst);
	sGameState = m_pMainMenu->GetStateMenu();
	m_Physics = Physics::GetInstance();
	m_Physics->InitializePhysics(m_pD3DDevice);
	m_pUIBar = UIBar::GetInstance();
	m_pUIBar->Initialize();
	m_pMiniGame = MiniGame::GetInstance();
	m_pMiniGame->InitMiniGame(m_pD3DDevice);
	m_pSound = Sound::GetSoundInstance();
	m_pSound->InitSounds();
	m_PowerUps = PowerUps::GetInstance();
	m_PowerUps->InitPowerUps(m_pD3DDevice);
	m_pLighting = Lighting::GetInstance();
	m_pLighting->InitLighting(m_pD3DDevice);
	m_pTimerBar = TimerBar::GetInstance();
	m_pTimerBar->Initialize();
	m_pVirusEnemy = VirusEnemy::GetInstance();
	m_pVirusEnemy->InitMines(m_pD3DDevice);
	m_pText = Text::GetInstance();
	m_pText->Init(m_pD3DDevice, hWnd);
	m_pPowerBar = PowerBar::GetInstance();
	m_pPowerBar->Initialize();
	m_pLevelManager = LevelManager::GetInstance();
	m_pLevelManager->Initialize();
	m_pInGameMenu = InGameMenu::GetInstance();
	m_pInGameMenu->InitInGameMenu(m_pD3DDevice);
	m_pHighScore = HighScore::GetInstance();
	m_pHighScore->InitHighScore(m_pD3DDevice, hWnd, hInst, m_pDirectInput);
	m_pEndGame = EndGame::GetInstance();
	m_pEndGame->Init(m_pD3DDevice, hWnd, hInst, m_pDirectInput, nWidth, nHeight);
	m_pTutorial = Tutorial::GetInstance();
	m_pTutorial->Initialize();
	//////////////////////////////////////////////////////////

	// Initialize score to 0
	sScore = 0;
	// Start off with no level loaded
	bLevelLoaded = false;
	iCurrLevel = 1;
	bMiniGameLoaded = false;
	bMusicLoaded = false;
	bSoundLoaded = false;
	bEndGameLoaded = false;
	// Checkpoint initialized
	sCheckpoint = 1;
	// Physics variable
	fVelChange = 0.017f;
}

void Gameplay::Update(HWND hWnd, HINSTANCE hInst, float deltaTime)
{
	//Update audio
	m_pSound->Update();

	// Game state switch
	switch(sGameState)
	{
	case MAINMENU:
		m_pMainMenu->Update(hWnd, m_pDirectInput);
		sGameState = m_pMainMenu->GetStateMenu();
		// Destroy the menu before going ingame
		if(sGameState == INGAME)
			m_pMainMenu->DestroyMenu();
		if(!bMusicLoaded)
		{
			m_pSound->MenuScreenMusic();
			bMusicLoaded = true;
		}
		// Play sound, once
		if(!bSoundLoaded)
		{
			m_pSound->IntroVoiceSFX();
			bSoundLoaded = true;
		}
		//Set the mouse positions for the Menu Highlights
		if(sGameState == MAINMENU)
		{
			if( m_pDirectInput->currentMousePos.x >= 77.0 && m_pDirectInput->currentMousePos.x <= 203.0 &&
				m_pDirectInput->currentMousePos.y >= 212.0 && m_pDirectInput->currentMousePos.y <= 262.0 )
			{
				m_pMainMenu->GetPlayGameHighlight();
			}
			else if( m_pDirectInput->currentMousePos.x >= 65.0 && m_pDirectInput->currentMousePos.x <= 288.0 &&
				m_pDirectInput->currentMousePos.y >= 309.0 && m_pDirectInput->currentMousePos.y <= 361.0 )
			{
				m_pMainMenu->GetCreditsHighlight();
			}
			else if( m_pDirectInput->currentMousePos.x >= 61.0 && m_pDirectInput->currentMousePos.x <= 553.0 &&
				m_pDirectInput->currentMousePos.y >= 404.0 && m_pDirectInput->currentMousePos.y <= 454.0 )
			{
				m_pMainMenu->GetInstructionsHighlight();
			}
			else if( m_pDirectInput->currentMousePos.x >= 59.0 && m_pDirectInput->currentMousePos.x <= 549.0 &&
				m_pDirectInput->currentMousePos.y >= 494.0 && m_pDirectInput->currentMousePos.y <= 546.0 )
			{
				m_pMainMenu->GetHighScoreHighlight();
			}
			else if( m_pDirectInput->currentMousePos.x >= 52.0 && m_pDirectInput->currentMousePos.x <= 165.0 &&
				m_pDirectInput->currentMousePos.y >= 590.0 && m_pDirectInput->currentMousePos.y <= 648.0 )
			{
				m_pMainMenu->GetQuitHighlight();
			}
			else
			{
				m_pMainMenu->RemoveHighlights();
			}
		}
		break;
	case INGAME:
		// Load level
		if(!bLevelLoaded)
		{
			if(iCurrLevel == 1)
				sScore = 0;
			m_pLevelManager->LoadLevel(iCurrLevel);
			sMiniGameCount = m_pLevelManager->GetMiniGameCount();
			m_pUIBar->LoadUIBar(sMiniGameCount);
			m_pTimerBar->LoadTimerBar(true);
			m_pPowerBar->LoadPowerBar();
			m_pInGameMenu->LoadPauseMenu();
			m_pCamera->LoadSkybox();
			if(iCurrLevel < 6)
				m_pTutorial->LoadTutorial(iCurrLevel);
			m_pCamera->SwitchToBuildCam();
			sPreLoadedModels = m_pLevelManager->GetPreModels();
			iModelCount = sPreLoadedModels;
			sPrePowerUps = m_pLevelManager->GetPowerUps();
			sPreTeslaCoil = m_pLevelManager->GetPreTeslaCoil();
			sPrePiston = m_pLevelManager->GetPrePiston();
			sPreAcidPit = m_pLevelManager->GetPreAcidPit();
			sPreFirewall = m_pLevelManager->GetPreFirewall();
			m_Physics->ResetVelocity();
			bLevelLoaded = true;
			bMusicLoaded = false;
			bSoundLoaded = false;
			bTrackSelected = false;
			bBuildMode = true;
			bFightMode = false;
			bSwitchedMode = false;
			bJumpOn = false;
			bJumpComplete = true;
			bPaused = false;
			bFightDone = false;
			sCheckpoint = 1;
			sCheckpointScore = sScore;
			sPowerUpsGathered = sPrePowerUps;
			vecLastPlacement = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
			m_pModelManager->CheckShieldStatus(sMiniGameCount);
		}
		else
		{
			if(!bMusicLoaded)
			{
				m_pSound->LevelMusic(iCurrLevel);
				bMusicLoaded = true;
			}
			////////////////////////////////////////////////////
			//DIRECT INPUT CODE STARTS//////////////////////////
			m_pDirectInput->Update(hWnd);
			////////////////////////////////////////////////////
			// PLAYER MOVEMENTS
			// 'D' key was pressed			
			if(m_pDirectInput->CheckKeyboard(DIK_ESCAPE))
			{
				if(!bKeyDown[DIK_ESCAPE])
				{
					if(bPaused)
						bPaused = false;
					else
					{
						bPaused = true;
						m_pInGameMenu->ResetInGameMenu();
					}
					bKeyDown[DIK_ESCAPE] = true;
				}
			}
			else
				bKeyDown[DIK_ESCAPE] = false;
			if(!bPaused)
			{
				if(m_pCamera->m_eyePos.y + m_pDirectInput->CheckMouseScroll() / 100.0f < 25.0f &&
					m_pCamera->m_eyePos.y + m_pDirectInput->CheckMouseScroll() / 100.0f > 2.0f)
				{
					iYCamChange = m_pDirectInput->CheckMouseScroll() * 5;
					m_pCamera->ModifyCameraPos(deltaTime, 0.0f, (float)iYCamChange, 0.0f);
				}
				if( m_pDirectInput->CheckKeyboard(DIK_D) )
				{
					if( !bBuildMode )
					{
						m_Physics->ChangeVelocityXPos(fVelChange, deltaTime);
					}
					else if(m_pCamera->m_eyePos.x < m_pCamera->fXBound)
					{
						m_pCamera->ModifyCameraPos(deltaTime, 10.0f, 0.0f, 0.0f);
					}
				}
				// 'A' key was pressed
				if( m_pDirectInput->CheckKeyboard(DIK_A) )
				{
					if( !bBuildMode )
					{
						m_Physics->ChangeVelocityXNeg(fVelChange, deltaTime);
					}
					else if(m_pCamera->m_eyePos.x > m_pCamera->fXNegBound)
					{
						m_pCamera->ModifyCameraPos(deltaTime, -10.0f, 0.0f, 0.0f);
					}
				}
				// 'S' key was pressed
				if( m_pDirectInput->CheckKeyboard(DIK_S) )
				{
					if( !bBuildMode )
					{
						m_Physics->ChangeVelocityZNeg(fVelChange, deltaTime);											
					}
					else if(m_pCamera->m_eyePos.z > m_pCamera->fZNegBound)
					{
						m_pCamera->ModifyCameraPos(deltaTime, 0.0f, 0.0f,  -10.0f);
					}

				}
				// 'W' key was pressed
				if( m_pDirectInput->CheckKeyboard(DIK_W) )
				{
					if( !bBuildMode )
					{
						m_Physics->ChangeVelocityZPos(fVelChange, deltaTime);											
					}
					else if(m_pCamera->m_eyePos.z < m_pCamera->fZBound)
					{
	 					m_pCamera->ModifyCameraPos(deltaTime, 0.0f, 0.0f, 10.0f);
					}
				}
				// Bring velocity back down to zero, no action
				if(!m_pDirectInput->CheckKeyboard(DIK_W) && !m_pDirectInput->CheckKeyboard(DIK_S) )
				{
					m_Physics->SlowVelocityZ(fVelChange + 0.001f, deltaTime);
				}
				if(!m_pDirectInput->CheckKeyboard(DIK_A) && !m_pDirectInput->CheckKeyboard(DIK_D))
				{
					m_Physics->SlowVelocityX(fVelChange + 0.001f, deltaTime);
				}
				// Check collision with Firewalls
				if(m_pObstacleManager->FireWallLoop())
				{
					//Player will rebound off of the firewall, bounce back
					//is based off of player's current velocity.
					m_Physics->NegateVelocity(deltaTime);
					if(!bSoundLoaded)
					{
						m_pSound->FireWallCollisionSFX();
						bSoundLoaded = true;
					}
				}
				else
					bSoundLoaded = false;			
				// Rotate track when space is pressed
				if( m_pDirectInput->CheckKeyboard(DIK_SPACE) )
				{
					if( bTrackSelected )
					{
						if( !bKeyDown[DIK_SPACE] )
						{
							if(!bSoundLoaded)
							{
								m_pSound->TrackRotateSFX();
								bSoundLoaded = true;
							}
							// Send in the player choice as model ID
							m_pModelManager->ModifyModelRot(iModelCount, -1.57f, 0.0f, 0.0f);

							bKeyDown[DIK_SPACE] = true;
						}
					}
				}
				else
				{
					bKeyDown[DIK_SPACE] = false;
					bSoundLoaded = false;
				}
				////////////////////////////////////////////////////

				// Change camera views
				if( m_pDirectInput->CheckKeyboard(DIK_R) )
				{
					if( !bKeyDown[DIK_R] )
					{
						// Switch out of build mode
						if(!bTrackSelected && !bFightMode)
						{
							if(!bSoundLoaded)
							{
								m_pSound->CameraShiftSFX();
								bSoundLoaded = true;
							}
							m_pCamera->SwtichToBehindCam();
							bBuildMode = false;
							m_pPowerBar->SetCheckpoint();
						}
						// Switch to run the path during fight mode
						else if(!bTrackSelected && bFightMode)
						{
							if(!bSoundLoaded)
							{
								m_pSound->CameraShiftSFX();
								bSoundLoaded = true;
							}
							m_pCamera->SwitchToFightCam();
							bBuildMode = false;
							m_pPowerBar->SetCheckpoint();
						}
						bKeyDown[DIK_R] = true;
					}
				}
				else
				{
					bKeyDown[DIK_R] = false;
					bSoundLoaded = false;
				}

				//*********************************************************************
				// Hot key buttons  1-3 so it would be the same as if clicking on them
				if( m_pDirectInput->CheckKeyboard(DIK_1) || m_pDirectInput->CheckKeyboard(DIK_NUMPAD1))
				{
					// Pressing 1 will load a turn track piece or white orb depending on game mode
					if(!bKeyDown[DIK_1] && !bKeyDown[DIK_NUMPAD1])
					{
						if( bBuildMode && !bTrackSelected && m_pPowerBar->CheckPowerLevel() > 0)
						{
							if(!bSoundLoaded)
							{
								m_pSound->TrackSelectedSFX();
								bSoundLoaded = true;
							}
							//Render the track piece that you selected (turning track piece)
							iModelCount = m_pModelManager->LoadModel("Models\\TurnTrk.X", D3DXVECTOR3(0.0f, 0.0f, 0.0f), false);
							bTrackSelected = true;
							bTrackPlaced = false;
							bTrackDeleted = false;
						}
					}
					bKeyDown[DIK_1] = true;
					bKeyDown[DIK_NUMPAD1] = true;
				}				
				else
				{
					bKeyDown[DIK_1] = false;
					bKeyDown[DIK_NUMPAD1] = false;
					bSoundLoaded = false;
				}
				if( m_pDirectInput->CheckKeyboard(DIK_2) || m_pDirectInput->CheckKeyboard(DIK_NUMPAD2) )
				{
					// Pressing 2 will load a straight track piece or red orb depending on game mode
					if(!bKeyDown[DIK_2] && !bKeyDown[DIK_NUMPAD2])
					{
						if( bBuildMode && !bTrackSelected && m_pPowerBar->CheckPowerLevel() > 0)
						{
							if(!bSoundLoaded)
							{
								m_pSound->TrackSelectedSFX();
								bSoundLoaded = true;
							}
							//Render the track piece that you selected (straight track piece)
							iModelCount = m_pModelManager->LoadModel("Models\\StrTrk.X", D3DXVECTOR3(0.0f, 0.0f, 0.0f), false);										
							bTrackSelected = true;
							bTrackPlaced = false;
							bTrackDeleted = false;
						}
						bKeyDown[DIK_1] = true;
						bKeyDown[DIK_NUMPAD2] = true;
					}
				}
				else
				{
					bKeyDown[DIK_2] = false;
					bKeyDown[DIK_NUMPAD2] = false;
					bSoundLoaded = false;
				}

				//Check to see if the Mouse Button was Pressed
				//0=Left Button, 1=Right Button
				if( m_pDirectInput->CheckMouseButtons(0) )
				{
					if( bBuildMode )
					{
						if( !bTrackSelected)
						{
							if(m_pPowerBar->CheckPowerLevel() > 0)
							{
								//Collision with the UI icon sprites
								// STRAIGHT TRACK
								if( m_pSpriteManager->SpriteCollision(m_pUIBar->sStraightTrackButton, m_pDirectInput->currentMousePos) )
								{
									if(!bSoundLoaded)
									{
										m_pSound->TrackSelectedSFX();
										bSoundLoaded = true;
									}
									//Render the track piece that you selected (straight track piece)
									iModelCount = m_pModelManager->LoadModel("Models\\StrTrk.X", D3DXVECTOR3(0.0f, 0.0f, 0.0f), false);
									bTrackSelected = true;
									bTrackPlaced = false;
									bTrackDeleted = false;
								}
								else
									bSoundLoaded = false;
								// TURN TRACK
								if( m_pSpriteManager->SpriteCollision(m_pUIBar->sCurveTrackButton, m_pDirectInput->currentMousePos) )
								{
									if(!bSoundLoaded)
									{
										m_pSound->TrackSelectedSFX();
										bSoundLoaded = true;
									}
									//Render the track piece that you selected (turning track piece)
									iModelCount = m_pModelManager->LoadModel("Models\\TurnTrk.X", D3DXVECTOR3(0.0f, 0.0f, 0.0f), false);
									bTrackSelected = true;
									bTrackPlaced = false;
									bTrackDeleted = false;
								}
								else
									bSoundLoaded = false;

								// UNDO BUTTON
								if( m_pSpriteManager->SpriteCollision(m_pUIBar->sUndo, m_pDirectInput->currentMousePos) )
								{
									if( iModelCount > sPreLoadedModels )
									{
										if( !bTrackDeleted )
										{
											if(!bSoundLoaded)
											{
												m_pSound->UndoButtonClickSFX();
												bSoundLoaded = true;
											}
											// Delete the last track that was placed
											m_pModelManager->DestroyModel(iModelCount);
											iModelCount--;
											bTrackDeleted = true;
										}
										else
											bSoundLoaded = false;
									}
								}
							}
							// UNDO ALL BUTTON
							if( m_pSpriteManager->SpriteCollision(m_pUIBar->sUndoAll, m_pDirectInput->currentMousePos) )
							{
								if( iModelCount > sPreLoadedModels )
								{
									for(int i = iModelCount; i != sPreLoadedModels; i--)
									{
										{
											m_pModelManager->DestroyModel(i);
											iModelCount--;
										}
									}
								}
								m_pPowerBar->FullPower();
							}
						}
						else
						{
							if( !bTrackPlaced )
							{
								if( !m_pSpriteManager->SpriteCollision(m_pUIBar->sUIBar, m_pDirectInput->currentMousePos) )
								{
									if( bTrackPlaceable )
									{
										if(!bSoundLoaded)
										{
											m_pSound->TrackPlacedCorrectSFX();
											bSoundLoaded = true;
										}
										//Right Mouse Button was Pressed, Place the previous selected piece
										vecRayPos = m_pCamera->CreateRay(m_pDirectInput->currentMousePos, bFightMode);
										m_pModelManager->PlaceTrack(iModelCount, vecRayPos->x, vecRayPos->y, vecRayPos->z, true, bFightMode);
										bTrackPlaced = true;
										bTrackSelected = false;
										bSoundLoaded = false;
										// when tracks are placed, player loses power bar energy
										// everytime track is placed subtract energy from powerlevel
										m_pPowerBar->ChangePowerLevel(-5);
									}
									else
										if(!bSoundLoaded)
										{
											m_pSound->TrackPlacedIncorrectSFX();
											bSoundLoaded = true;
										}
										bSoundLoaded = false;
								}
							}
						}
					}
				}
				else if( m_pDirectInput->CheckMouseButtons(1) )
				{
					if( bBuildMode )
					{
						if( bTrackSelected && !bTrackPlaced )
						{
							if(!bSoundLoaded)
							{
								m_pSound->TrackPlaceCancel();
								bSoundLoaded = true;
							}
							m_pModelManager->DestroyModel(iModelCount);
							iModelCount--;
							bTrackSelected = false;
						}
						else
							bSoundLoaded = false;
					}
				}
				// DIRECT INPUT CODE ENDS HERE
				////////////////////////////////////////////////////
				// GAMEPLAY CODE STARTS
				// Update the camera in every frame to keep following the player
				// only when behind view is on
				if( !bBuildMode )
					m_pCamera->UpdateCamera(bFightMode, bJumpComplete);
				// Tutorial updating
				if(iCurrLevel < 6)
				{
					if(iCurrLevel == 1) 
					{
						if(bBuildMode)
						{
							if(iModelCount == 14)
								m_pTutorial->sTrigger = 1;
							else if(iModelCount == 15)
								m_pTutorial->sTrigger = 2;
						}
						else if(sScore == 0)
							m_pTutorial->sTrigger = 3;
						else if(sScore > 10 && sScore < 30)
							m_pTutorial->sTrigger = 4;
					}
					else if(iCurrLevel == 2)
					{
						if(sMiniGameCount == 1)
						{
							if(iModelCount == 14)
								m_pTutorial->sTrigger = 0;
							else if(!bBuildMode && m_pModelManager->CollisionDetection(1))
								m_pTutorial->sTrigger = 1;
							else if(m_pModelManager->CollisionDetection(8))
								m_pTutorial->sTrigger = 4;
							else
								m_pTutorial->sTrigger = -1;
						}
						else
							m_pTutorial->sTrigger = -1;
					}
					else if(iCurrLevel == 3)
					{
						if(iModelCount == 14)
							m_pTutorial->sTrigger = 0;
						else if(!bBuildMode && m_pModelManager->CollisionDetection(1))
							m_pTutorial->sTrigger = 4;
						else
							m_pTutorial->sTrigger = -1;
					}
					else if(iCurrLevel == 4)
					{
						if(m_pModelManager->CollisionDetection(2))
							m_pTutorial->sTrigger = 0;
						else if(!bBuildMode && m_pModelManager->CollisionDetection(3))
							m_pTutorial->sTrigger = 4;
						else
							m_pTutorial->sTrigger = -1;
					}
					else if(iCurrLevel == 5)
					{
						if(bBuildMode && m_pModelManager->CollisionDetection(1))
							m_pTutorial->sTrigger = 0;
						else if(!bBuildMode && m_pModelManager->CollisionDetection(1))
							m_pTutorial->sTrigger = 4;
						else
							m_pTutorial->sTrigger = -1;
					}
					m_pTutorial->Update();
				}

				// Keep updating the track position based on mouse position if selected
				if( bTrackSelected )
				{
					vecRayPos = m_pCamera->CreateRay(m_pDirectInput->currentMousePos, bFightMode);
					// Manipulate the track following the mouse to fit within the boundaries
					if(vecRayPos->x < m_pCamera->fXNegBound)
						vecRayPos->x = m_pCamera->fXNegBound;
					if(vecRayPos->x > m_pCamera->fXBound)
						vecRayPos->x = m_pCamera->fXBound;
					if(vecRayPos->z > m_pCamera->fZBound)
						vecRayPos->z = m_pCamera->fZBound;

					// Snap feature (GRID SYSTEM)
					float fCurrX = vecRayPos->x - vecLastPlacement.x;
					float fCurrZ = vecRayPos->z - vecLastPlacement.z;
					if(fCurrX > 0.05 || fCurrX < -0.05)
					{
						if(fCurrZ > 0.05 || fCurrZ < -0.05)
						{
							m_pModelManager->PlaceTrack(iModelCount, vecRayPos->x, 0.0f, vecRayPos->z, true, bFightMode);
							vecLastPlacement.x = vecRayPos->x;
							vecLastPlacement.z = vecRayPos->z;
						}
						else
						{
							m_pModelManager->PlaceTrack(iModelCount, vecRayPos->x, 0.0f, vecLastPlacement.z, true, bFightMode);
							vecLastPlacement.x = vecRayPos->x;
						}
					}
					else if(fCurrZ > 0.05 || fCurrZ < -0.05)
					{
						m_pModelManager->PlaceTrack(iModelCount, vecLastPlacement.x, 0.0f, vecRayPos->z, true, bFightMode);
						vecLastPlacement.z = vecRayPos->z;
					}

					//*********************************************************************
					//// Check collision between all models and current selected track
					//for(int i = 0; i < iModelCount; i++)
					//{
					//	if(!m_pModelManager->TrackPlacementCollision(iModelCount, i))
					//	{
					//		// If not colliding, the track is placeable
					//		bTrackPlaceable = true;
					//	}
					//	else
					//	{
					//		// If colliding, the track is not placeable
					//		bTrackPlaceable = false;
					//		break;
					//	}
					//}
					//*********************************************************************
					// If the track is below the minimum Z bound, can't place it there
					if(vecRayPos->x >= m_pCamera->fXBound)
						bTrackPlaceable = false;
					if(vecRayPos->x <= m_pCamera->fXNegBound)
						bTrackPlaceable = false;
					if(vecRayPos->z < m_pCamera->fZNegBound)
						bTrackPlaceable = false;
					if(vecRayPos->z >= m_pCamera->fZBound)
						bTrackPlaceable = false;
					if(vecRayPos->x < m_pCamera->fXBound && vecRayPos->x > m_pCamera->fXNegBound
						&& vecRayPos->z > m_pCamera->fZNegBound && vecRayPos->z < m_pCamera->fZBound)
						bTrackPlaceable = true;
				}

				// Check gravity to put the player on top of the tracks
				if(bLevelLoaded)
				{
					m_Physics->GravityCheck(iModelCount, deltaTime, bJumpOn);
				}

				// Checking if the player has fallen off the tracks
				vecPlayerPos = m_pModelManager->GetPlayerPos();
				if( vecPlayerPos.y < -10.0f )
					Reset(sCheckpoint);

				// Check collision with the power ups
				if(!bBuildMode)
				{
					for(int i = 0; i < sPowerUpsGathered; i++)
					{
						if(m_PowerUps->MagnetCollisionDetection(i))
						{
							if(!m_PowerUps->CollisionDetection(i))
								m_PowerUps->StartPull(i, deltaTime);
							else
							{
								if(!bSoundLoaded)
								{
									m_pSound->MaterialOrbCollisionSFX();
									bSoundLoaded = true;
								}
								sPrePowerUps--;
								sScore = sScore + 10;
								bSoundLoaded = false;
							}
						}
					}
				}

				// Call TimerBar update
				if(!bBuildMode)
					m_pTimerBar->Update(iModelCount, sPreLoadedModels);
				// Check the life/timer
				// Reset everything with the player and track placements
				iTimer = m_pTimerBar->CheckTime();
				if(iTimer == m_pTimerBar->sEnergyBarEmpty)
					Reset(sCheckpoint);
				// Update virus only in fight mode
				if(!bBuildMode && bFightMode)
					m_pVirusEnemy->UpdateMines(deltaTime);
				// Update score
				m_pText->Incriment(sScore);
				// Update Obstacle Manager
				m_pObstacleManager->Update(deltaTime);
				// Update the power bar to change
				m_pPowerBar->Update();
				// Check collision with Obstacles
				for(int i = 0; i <= sPreTeslaCoil; i++)
				{
					if(m_pObstacleManager->TeslaCollision(i))
					{
						if(!bSoundLoaded)
						{
							m_pSound->TeslaCoilCollisionSFX();
							bSoundLoaded = true;
						}
						Reset(sCheckpoint);
					}
					else
						bSoundLoaded = false;
				}
				for(int i = 0; i <= sPreAcidPit; i++)
				{
					if(m_pObstacleManager->AcidCollision(i))
					{
						if(!bSoundLoaded)
						{
							m_pSound->AcidPitCollisionSFX();
							bSoundLoaded = true;
						}
						Reset(sCheckpoint);
					}
					else
						bSoundLoaded = false;
				}
				for(int i = 0; i <= sPrePiston; i++)
				{
					if(m_pObstacleManager->PistonCollision(i))
					{
						if(!bSoundLoaded)
						{
							m_pSound->PistonCollisionSFX();
							bSoundLoaded = true;
						}
						Reset(sCheckpoint);
					}
					else
						bSoundLoaded = false;
				}	
				if(m_pModelManager->ShieldCollision())
				{
					Reset(sCheckpoint);
				}

				// Check Collision with the checkpoints
				// JUMP PAD
				if( m_pModelManager->CollisionDetection(13) )
				{
					if(!bSoundLoaded)
					{
						m_pSound->JumpPadCollisionSFX();
						bSoundLoaded = true;
					}
					// Jump the character to make the transition between modes
					bJumpOn = true;
					bJumpComplete = false;
				}
				else
					bSoundLoaded = false;
				// Jump is going on
				if(bJumpOn || m_pVirusEnemy->bExplosion)
				{
					bJumpOn = m_Physics->Jump(deltaTime);
					m_pVirusEnemy->bExplosion = bJumpOn;
				}
				// Collided with the platforms that switch modes
				// TO FIGHT
				if( m_pModelManager->CollisionDetection(3) && !bJumpOn && !bSwitchedMode)
				{
					sCheckpoint = 3;
					sCheckpointScore = sScore;
					sPreLoadedModels = iModelCount;
					m_pCamera->SwitchToBuildCam();
					m_pPowerBar->SetCheckpoint();
					m_pTimerBar->SetCheckpoint();
					bBuildMode = true;
					bFightMode = true;
					bSwitchedMode = true;
					bJumpComplete = true;
				}
				// TO LOWER LEVEL
				if( m_pModelManager->CollisionDetection(4) && bSwitchedMode)
				{
					sCheckpoint = 4;
					sCheckpointScore = sScore;
					sPreLoadedModels = iModelCount;
					m_pCamera->SwitchToBuildCam();
					m_pPowerBar->SetCheckpoint();
					m_pTimerBar->SetCheckpoint();
					bBuildMode = true;
					bFightMode = false;
					bSwitchedMode = false;
					bFightDone = true;
				}
				// TERMINAL 1
				if( m_pModelManager->CollisionDetection(5))
				{
					sMiniGameID = m_pLevelManager->GetMiniGameID1();
					sTerminal = 5;
					sGameState = MINIGAME;
				}
				// TERMINAL 2
				if( m_pModelManager->CollisionDetection(6))
				{
					sMiniGameID = m_pLevelManager->GetMiniGameID2();
					sTerminal = 6;
					sGameState = MINIGAME;
				}
				// TERMINAL 3
				if( m_pModelManager->CollisionDetection(7))
				{
					sMiniGameID = m_pLevelManager->GetMiniGameID3();
					sTerminal = 7;
					sGameState = MINIGAME;
				}
				// FINAL DOOR
				if( m_pModelManager->CollisionDetection(12) && iCurrLevel == 10) // Have 9 curr levels rigth now
				{
					sGameState = ENDGAME;
					m_pEndGame->GetScore(sScore);
				}	
				// DOOR
				else if( m_pModelManager->CollisionDetection(12))
				{
					iCurrLevel++;
					Reset();
				}
				/*if( m_pDirectInput->CheckKeyboard(DIK_F) && m_pDirectInput->CheckKeyboard(DIK_U) )
				{
					iCurrLevel++;
					Reset();
				}*/
				// GAMEPLAY CODE ENDS
			}
			else			
			{
				m_pInGameMenu->Update(hWnd, m_pDirectInput);
				bPaused = m_pInGameMenu->GetPaused();
				sGameState = m_pInGameMenu->GetStateIGMenu();
				if(sGameState == MAINMENU)
				{
					Reset();						
					m_pMainMenu->InitMainMenu(m_pD3DDevice, hWnd, hInst);
					bPaused = false;
					iCurrLevel = 1;
					bMusicLoaded = false;
				}
				if(sGameState == 4)
				{
					sCheckpoint = 1;
					Reset();
					sGameState = INGAME; // gamestate needs to stay as 1 to continue playing
					bPaused = false;
				}
			}
		}
		break;
	case MINIGAME:
		if(!bMiniGameLoaded)
		{
			if(iCurrLevel < 6)
				m_pTutorial->DestroyTutorial();
			m_pInGameMenu->DestroyIGMenu();
			m_pPowerBar->DestroyPower();
			m_pTimerBar->DestroyTimer();
			m_pUIBar->DestroyUI();
			m_pMiniGame->LoadMiniGame(sMiniGameID, sTerminal);
			bMiniGameLoaded = true;
			bMusicLoaded = false;
			bSoundLoaded = false;
		}
		else
		{
			if(!bMusicLoaded)
			{
				m_pSound->MiniGameMusic();
				bMusicLoaded = true;
			}
			m_pMiniGame->Update(hWnd, m_pDirectInput);
			sGameState = m_pMiniGame->GetStateMiniGame();
			if(sGameState == INGAME)
			{
				if(m_pMiniGame->CheckTerminal1Beat())
				{
					sPreLoadedModels = iModelCount;
					// if mini game is beat decrease minigamecount, then check shield status
					--sMiniGameCount;
					m_pModelManager->CheckShieldStatus(sMiniGameCount);
					if(sTerminal == 5)
					{
						sCheckpoint = 8;
						sPowerUpsGathered = sPrePowerUps;
						sCheckpointScore = sScore;
						m_pPowerBar->FullPower();
						m_pPowerBar->SetCheckpoint();
					}
					if(sTerminal == 6)
					{
						sCheckpoint = 9;
						sPowerUpsGathered = sPrePowerUps;
						sCheckpointScore = sScore;
						m_pPowerBar->FullPower();
						m_pPowerBar->SetCheckpoint();
					}
					if(sTerminal == 7)
					{
						sCheckpoint = 10;
						sPowerUpsGathered = sPrePowerUps;
						sCheckpointScore = sScore;
						m_pPowerBar->FullPower();
						m_pPowerBar->SetCheckpoint();
					}
				}
				m_pMiniGame->DestroyMiniGame();
				bMiniGameLoaded = false;
				bMusicLoaded = false;
				bSoundLoaded = false;
				m_pUIBar->LoadUIBar(sMiniGameCount);
				m_pTimerBar->LoadTimerBar(false);
				m_pPowerBar->LoadPowerBar();
				m_pInGameMenu->LoadPauseMenu();
				if(iCurrLevel < 6)
					m_pTutorial->LoadTutorial(iCurrLevel);
				Reset(sCheckpoint);
			}
		}
		break;
	case ENDGAME:
		if(!bEndGameLoaded)
		{
			m_pSpriteManager->DestroyAllSprites();
			m_pEndGame->LoadEndGameSprites();
			bEndGameLoaded = true;
		}
		else
		{
			m_pEndGame->Update(hWnd, hInst, deltaTime);
			sGameState = m_pEndGame->GetStateEndGame();
			if(sGameState == MAINMENU)
			{
				Reset();						
				m_pMainMenu->InitMainMenu(m_pD3DDevice, hWnd, hInst);
				bPaused = false;
				iCurrLevel = 1;
			}

		}
		break;
	}
}

void Gameplay::Render(float deltaTime)
{
	switch(sGameState)
	{
	case MAINMENU:
		// Render the main menu
		m_pMainMenu->Render(m_pD3DDevice);
		break;
	case INGAME:
		// Render the game level
		if(bLevelLoaded)
		{
			m_pModelManager->DrawModel();
			m_pUIBar->Render();
			m_pTimerBar->Render();
			m_pPowerBar->Render();
			m_PowerUps->RenderPowerUps();
			m_pVirusEnemy->RenderMines();
			m_pCamera->RenderWorldPlane();
			m_pObstacleManager->DrawModel(deltaTime);
			m_pText->RenderScore();
			m_pText->SetLevel(iCurrLevel);
			m_pTutorial->RenderTutorial();
			if(bPaused)
			{
				m_pUIBar->RenderPause();
				m_pInGameMenu->Render(m_pD3DDevice);	
			}
		}
		break;
	case MINIGAME:
		// Render the mini game
		if(bMiniGameLoaded)
			m_pMiniGame->Render(m_pD3DDevice);
		break;
	case ENDGAME:
		if(bEndGameLoaded)
		{
			m_pEndGame->Render();
		}
		break;
	}
}

void Gameplay::Reset(short sCheckpoint)
{
	m_pModelManager->ResetPlayer(sCheckpoint);
	m_pTimerBar->FullEnergy();
	m_pPowerBar->ResetPower();
	m_pModelManager->bFirstTrack = true;
	m_pModelManager->bJumping = false;
	m_pModelManager->iPathTimer = 0;
	m_Physics->ResetVelocity();
	m_pVirusEnemy->ReactivateMines();
	m_PowerUps->DestroyPowerUps();
	m_PowerUps->UpdatePowerUps(sPowerUpsGathered, bFightDone);
	bJumpComplete = true;
	bBuildMode = true;
	sScore = sCheckpointScore;
	bTrackSelected = false;
	m_pCamera->SwitchToBuildCam();
	m_pTutorial->sTrigger = -1;
}

void Gameplay::Reset()
{
	m_pTimerBar->FullEnergy();
	m_pPowerBar->FullPower();
	m_pModelManager->DestroyAllModels();
	m_pCamera->DestroySkybox();
	m_pObstacleManager->DestroyAllObstacles();
	m_PowerUps->DestroyPowerUps();
	m_pVirusEnemy->ClearMineList();
	m_pSpriteManager->DestroyAllSprites();
	m_pHighScore->strLName = "";
	m_pHighScore->bPass = false;
	bEndGameLoaded = false;
	m_pTutorial->sTrigger = -1;
	bLevelLoaded = false;
}

void Gameplay::Shutdown(void)
{
	// Delete Tutorial class
	if(m_pTutorial)
	{
		m_pTutorial->DeleteInstance();
		m_pTutorial = NULL;
	}
	// Delete EndGame class
	if(m_pEndGame)
	{
		m_pEndGame->DeleteEndGameInstance();
		m_pEndGame = NULL;
	}
	// Delete In High Score class
	if(m_pHighScore)
	{
		m_pHighScore->DeleteHighScoreInstance();
		m_pHighScore = NULL;
	}
	// Delete In Game Menu class
	if(m_pInGameMenu)
	{
		m_pInGameMenu->DeleteInGameMenuInstance();
		m_pInGameMenu = NULL;
	}
	// Delete the LevelManager class
	if(m_pLevelManager)
	{
		m_pLevelManager->DeleteLevelInstance();
		m_pLevelManager = NULL;
	}
	// Delete the powerBar class
	if(m_pPowerBar)
	{
		delete m_pPowerBar;
		m_pPowerBar = NULL;
	}	
	// Delete the Text class
	if(m_pText)
	{
		m_pText->DeleteTextInstance();
		m_pText = NULL;
	}
	// Delete the VirusEnemy class
	if(m_pVirusEnemy)
	{
		m_pVirusEnemy->DeleteVirusInstance();
		m_pVirusEnemy = NULL;
	}
	//Delete the timerBar class
	if(m_pTimerBar)
	{
		m_pTimerBar->DeleteTimerBarInstance();
		m_pTimerBar = NULL;
	}	
	//Delete the sound class
	if(m_pLighting)
	{
		m_pLighting->DeleteLightingInstance();
		m_pLighting = NULL;
	}
	// Delete the Power ups class
	if(m_PowerUps)
	{
		m_PowerUps->DeletePowerInstance();
		m_PowerUps = NULL;
	}
	// Delete the Sound instance
	if(m_pSound)
	{
		m_pSound->DeleteInstance();
		m_pSound = NULL;
	}
	// Delete the MiniGame instance
	if(m_pMiniGame)
	{
		m_pMiniGame->DeleteMiniGameInstance();
		m_pMiniGame = NULL;
	}
	// Delete the UI Bar instance
	if(m_pUIBar)
	{
		m_pUIBar->DeleteUIBarInstance();
		m_pUIBar = NULL;
	}
	// Delete the Physics instance
	if(m_Physics)
	{
		m_Physics->DeleteInstance();
		m_Physics = NULL;
	}
	// Delete the MainMenu instance
	if(m_pMainMenu)
	{
		m_pMainMenu->DeleteMenuInstance();
		m_pMainMenu = NULL;
	}
	// Delete the ObstacleManager instance
	if(m_pObstacleManager)
	{
		m_pObstacleManager->DeleteInstance();
		m_pObstacleManager = NULL;
	}
	// Delete the SpriteManger instance
	if(m_pSpriteManager)
	{
		m_pSpriteManager->DeleteSpriteInstance();
		m_pSpriteManager = NULL;
	}
	// Delete the ModelManager instance
	if(m_pModelManager)
	{
		m_pModelManager->DeleteInstance();
		m_pModelManager = NULL;
	}
	if(m_pCamera)
	{
		m_pCamera->DeleteInstance();
		m_pCamera = NULL;
	}
	// Delete the DirectInput object
	if(m_pDirectInput)
	{
		delete m_pDirectInput;
		m_pDirectInput = NULL;
	}
}